package com.huang.canal.controller;

import com.alibaba.fastjson.JSON;
import com.huang.canal.client.CourseClient;
import com.huang.canal.entity.ESbean;
import com.huang.canal.entity.EsRequestParam;
import com.huang.canal.entity.EsResponseResoult;
import com.hunag.utils.R;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/canal")
public class EScontroller {

    @Autowired
    private RestHighLevelClient client;


    @Autowired
    private CourseClient esClient;

    @GetMapping("/t1")
    public List<ESbean> t1(@RequestParam("id") String id)  {
        return esClient.getOne2(id);
    }

    @RequestMapping("/loadAddToES")
    public Boolean toAll() throws IOException {
        List<ESbean> seviceAl = esClient.getTotal();
        IndexRequest request = new IndexRequest("course_db");
        IndexResponse response =null;
        for (ESbean sbean : seviceAl) {
            //规则 一般的文档形如 put /index/_doc/1
            request.id(sbean.getId());//如果不设置id的话会自动分配id
            request.timeout("1s");//设置超时时间
            //将我们的数据放入请求Json中
            request.source(JSON.toJSONString(sbean), XContentType.JSON);
            //客户端发送请求,获取相应的结果
            response = client.index(request,RequestOptions.DEFAULT);
        }
        return response.getShardInfo().getSuccessful()>0?true:false;
    }


    @RequestMapping("/createIndex")
    public boolean create(){
        //1.创建索引请求
        CreateIndexRequest request = new CreateIndexRequest("course_db");
        //2.客户端执行请求IndicesClient,请求后获得相应
        CreateIndexResponse response = null;
        try {
            response = client.indices().create(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response.isAcknowledged();
    }


    @PostMapping("/searchList")
    public R SearchList(@RequestBody EsRequestParam param ) throws IOException {
        System.out.println("param===>"+param);
        // 构建DSL语句
        SearchRequest searchRequest = startBuildRequestParam(param);
        //2、进行检索操作
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        //通过查询出来的结果 封装返回结果给予显示
        EsResponseResoult erList=getResoult(response,param);
        System.out.println(erList.getDataList().size()+"首页结果及大小为");
        return R.ok().data("res",erList);
    }



    private EsResponseResoult getResoult(SearchResponse response, EsRequestParam requestParam) {
        EsResponseResoult responseResult = new EsResponseResoult();
        SearchHits hits = response.getHits();

        // 所有课程数据
        ArrayList<ESbean> esModels = new ArrayList<ESbean>();
        if (hits.getHits() != null && hits.getHits().length > 0) {
            for (SearchHit hit : hits.getHits()) {
                String sourceAsString = hit.getSourceAsString();
                ESbean esModel = JSON.parseObject(sourceAsString, ESbean.class);
                //2.1 判断是否按关键字检索，若是就显示高亮，否则不显示
                if (!org.springframework.util.StringUtils.isEmpty(requestParam.getKeyword()) ){
                    //2.2 拿到高亮信息显示标题
                    HighlightField name = hit.getHighlightFields().get("title");
                    //2.3 判断name中是否含有查询的关键字(因为是多字段查询，因此可能不包含指定的关键字，假设不包含则显示原始name字段的信息)
                    String nameValue = name!=null ? name.getFragments()[0].string() : esModel.getTitle();
                    esModel.setTitle(nameValue);
                }
                esModels.add(esModel);
            }
        }
        responseResult.setDataList(esModels);

        //总数
        responseResult.setSize(hits.getTotalHits().value);
        System.out.println(hits.getTotalHits().value);

        //类型返回集合
        ArrayList<String> typeList = new ArrayList<>();
        ParsedStringTerms typeagg = response.getAggregations().get("type_agg");
        for (Terms.Bucket bucket : typeagg.getBuckets()) {
            String keyAsString = bucket.getKey().toString();
            typeList.add(keyAsString);
        }

        //类型返回集合
        ArrayList<String> publishList = new ArrayList<>();
        ParsedStringTerms  publishagg = response.getAggregations().get("publish_agg");
        for (Terms.Bucket bucket : publishagg.getBuckets()) {
            String keyAsString = bucket.getKeyAsString();
            publishList.add(keyAsString);
        }

        //类型返回集合
        ArrayList<String> careerList = new ArrayList<>();
        ParsedStringTerms careeragg = response.getAggregations().get("career_agg");
        for (Terms.Bucket bucket : careeragg.getBuckets()) {
            String keyAsString = bucket.getKeyAsString();
            careerList.add(keyAsString);
        }

        responseResult.setCareerList(careerList);
        responseResult.setTypeList(typeList);
        responseResult.setPublishList(publishList);


        //6、进行分页操作
//        responseResult.setPageNum(requestParam.getPageNum());
//        //获取总记录数
//        long total = hits.getTotalHits().value;
//        System.out.println("查询出来的数量====》"+total);
//        responseResult.setSize(total);
//
//        //计算总页码
//        int totalPages = (int) total % 4 == 0 ?
//                (int) total / 4 : ((int) total / 4 + 1);
//        responseResult.setTotalPages(totalPages);
//
//        List<Integer> pageNavs = new ArrayList<>();
//        for (int i = 1; i <= totalPages; i++) {
//            pageNavs.add(i);
//        }
//        responseResult.setPageNavs(pageNavs);
        return responseResult;
    }


    // 构建查询条件语句 DSL语句
    private SearchRequest startBuildRequestParam(EsRequestParam param) {

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); //所以查询条件
        // 构建bool查询田间
        BoolQueryBuilder boolquery=new BoolQueryBuilder();
        if(!StringUtils.isEmpty(param.getKeyword())){
            //多字段  关键字匹配
            boolquery.must(QueryBuilders.multiMatchQuery(param.getKeyword(),"title") );
        }

        if(null!=param.getCareer()){
            //多字段  关键字匹配
            boolquery.filter(QueryBuilders.termQuery("career.keyword",param.getCareer()) );
        }
        if(null!=param.getType()){
            //多字段  关键字匹配
            boolquery.filter(QueryBuilders.termQuery("type.keyword",param.getType()) );
        }
        if(null!= param.getPublish()){
            //多字段  关键字匹配
            boolquery.filter(QueryBuilders.termQuery("publish.keyword",param.getPublish()) );
        }

        // 价格的范围查询
        if(!StringUtils.isEmpty(param.getPrice())){
            //价格不为空   _10  10_100  100_
            String priceString=  param.getPrice();
            String[] priceList = param.getPrice().split("_");
            RangeQueryBuilder rangeQueryBuilder=new RangeQueryBuilder("price");

            if(StringUtils.startsWithIgnoreCase(priceString,"_")){
                // _10 小于10得情况
                rangeQueryBuilder.lte(priceList[0]);
            }else if(StringUtils.endsWithIgnoreCase(priceString,"_")){
                // 100_ 得情况
                rangeQueryBuilder.gte(priceList[0]);
            }else {
                // 10_100的情况
                rangeQueryBuilder.gte(priceList[0]).lte(priceList[1]);
            }
            boolquery.filter(rangeQueryBuilder);
        }

        sourceBuilder.query(boolquery);

        // 销量排序 sort     “price_acs    salecount_desc”
        if(!StringUtils.isEmpty(param.getSort())&&!"false".equals(param.getSort())){
            String  sort= param.getSort();
            System.out.println(sort+"<======");

            SortOrder sortOrder = "asc".equals(sort)?SortOrder.ASC:SortOrder.DESC;
            sourceBuilder.sort("buyCount",sortOrder);

        }

        //分页查询 封装
//        sourceBuilder.from((param.getPageNum() - 1) * 6);
        sourceBuilder.size(10000);

        //高亮显示
        if (!StringUtils.isEmpty(param.getKeyword())) {
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.field("title");
            highlightBuilder.preTags("<a style='color:red'>");
            highlightBuilder.postTags("</a>");
            sourceBuilder.highlighter(highlightBuilder);
        }




        //聚合查询  开始
        // 发行商 分组

            TermsAggregationBuilder publish_agg = AggregationBuilders.terms("publish_agg");
        publish_agg.field("publish.keyword");
            sourceBuilder.aggregation(publish_agg);


        // 课程类型

            TermsAggregationBuilder type_agg = AggregationBuilders.terms("type_agg");
            type_agg.field("type.keyword");
            sourceBuilder.aggregation(type_agg);



            TermsAggregationBuilder career_agg = AggregationBuilders.terms("career_agg");
            career_agg.field("career.keyword");
            sourceBuilder.aggregation(career_agg);





        System.out.println("构建的DSL语句 {}:"+ sourceBuilder.toString());

        SearchRequest searchRequest = new SearchRequest(new String[]{"course_db"}, sourceBuilder);
        return searchRequest;
    }

}